using System;
using System.Collections;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using PickGold.Charting;
using PickGold.Charting.Utilities;

namespace PickGold.Charting.ChartTypes
{
	internal class FunnelChart : IChartType, IDisposable
	{
		private Series _chartTypeSeries;
		private float _funnelMinPointHeight;
		private SizeF _funnelNeckSize = new SizeF(50f, 30f);
		private FunnelStyle _funnelStyle;
		private RectangleF _plotAreaPosition = RectangleF.Empty;
		private int _rotation3D = 5;
		private double[] _valuePercentages;
		private double _xValueTotal;
		private double _yValueMax;
		internal string funnel3DDrawingStyleAttributeName = "Funnel3DDrawingStyle";
		internal string funnelInsideLabelAlignmentAttributeName = "FunnelInsideLabelAlignment";
		internal string funnelLabelStyleAttributeName = "FunnelLabelStyle";
		protected string funnelOutsideLabelPlacementAttributeName = "FunnelOutsideLabelPlacement";
		internal string funnelPointGapAttributeName = "FunnelPointGap";
		protected string funnelPointMinHeight = "FunnelMinPointHeight";
		internal string funnelRotationAngleAttributeName = "Funnel3DRotationAngle";
		internal float funnelSegmentGap;
		internal bool isPyramid;
		internal ArrayList labelInfoList;
		internal RectangleF plotAreaSpacing = new RectangleF(3f, 3f, 3f, 3f);
		internal int pointNumber;
		internal bool round3DShape = true;
		internal ArrayList segmentList;
		internal double yValueTotal;

		public void AddSmartLabelMarkerPositions(CommonElements common, ChartArea area, Series series, ArrayList list)
		{
		}

		protected float CheckMinHeight(float height)
		{
			float num = Math.Min((float)2f, (float)(this.funnelSegmentGap / 2f));
			if ((this.funnelSegmentGap > 0f) && (height < num))
			{
				return num;
			}
			return height;
		}

		private ArrayList CreateLabelsInfoList()
		{
			var list = new ArrayList();
			var absoluteRectangle = this.Graph.GetAbsoluteRectangle(this.Area.Position.ToRectangleF());
			var dataSeries = this.GetDataSeries();
			if (dataSeries != null)
			{
				int num = 0;
				foreach (DataPoint point in dataSeries.Points)
				{
					if (!point.IsEmpty)
					{
						string label = point.Label;
						if (point.IsValueShownAsLabel || (label.Length > 0))
						{
							FunnelPointLabelInfo info = new FunnelPointLabelInfo();
							info.Point = point;
							info.PointIndex = num;
							if (label.Length == 0)
							{
								info.Text = ValueConverter.FormatValue(point.series.Chart, point, point.Tag, point.YValues[0], point.LabelFormat, point.series.YValueType, ChartElementType.DataPoint);
							}
							else
							{
								info.Text = point.ReplaceKeywords(label);
							}
							info.Style = this.GetLabelStyle(point);
							if (info.Style == FunnelLabelStyle.Inside)
							{
								info.VerticalAlignment = this.GetInsideLabelAlignment(point);
							}
							if (info.Style != FunnelLabelStyle.Inside)
							{
								info.OutsidePlacement = this.GetOutsideLabelPlacement(point);
							}
							info.Size = this.Graph.MeasureString(info.Text, point.Font, absoluteRectangle.Size, StringFormat.GenericTypographic);
							if ((info.Text.Length > 0) && (info.Style != FunnelLabelStyle.Disabled))
							{
								list.Add(info);
							}
						}
					}
					num++;
				}
			}
			return list;
		}

		public void Dispose()
		{
			this.Dispose(true);
			GC.SuppressFinalize(this);
		}

		protected virtual void Dispose(bool disposing)
		{
		}

		private void DrawFunnel3DSquareSegment(DataPoint point, int pointIndex, float startWidth, float endWidth, float location, float height, bool nothingOnTop, bool nothingOnBottom, bool drawSegment, bool drawSegmentShadow)
		{
			if (!nothingOnBottom)
			{
				height += 0.3f;
			}
			Color color = ChartGraphics.GetGradientColor(point.Color, Color.White, 0.3);
			Color color2 = ChartGraphics.GetGradientColor(point.Color, Color.Black, 0.3);
			if ((this._funnelStyle == FunnelStyle.YIsHeight) && !this.isPyramid)
			{
				if (startWidth < this._funnelNeckSize.Width)
				{
					startWidth = this._funnelNeckSize.Width;
				}
				if (endWidth < this._funnelNeckSize.Width)
				{
					endWidth = this._funnelNeckSize.Width;
				}
			}
			float num = (float)((startWidth / 2f) * Math.Sin((((float)this._rotation3D) / 180f) * 3.1415926535897931));
			float num2 = (float)((endWidth / 2f) * Math.Sin((((float)this._rotation3D) / 180f) * 3.1415926535897931));
			RectangleF absoluteRectangle = this.Graph.GetAbsoluteRectangle(this.PlotAreaPosition);
			float num3 = absoluteRectangle.X + (absoluteRectangle.Width / 2f);
			this.Graph.StartHotRegion(point);
			GraphicsPath path = new GraphicsPath();
			if (startWidth > 0f)
			{
				path.AddLine(num3 - (startWidth / 2f), location, num3, location + num);
			}
			path.AddLine(num3, location + num, num3, (location + height) + num2);
			if (endWidth > 0f)
			{
				path.AddLine(num3, (location + height) + num2, num3 - (endWidth / 2f), location + height);
			}
			path.AddLine(num3 - (endWidth / 2f), location + height, num3 - (startWidth / 2f), location);
			if (this.Common.ProcessModePaint)
			{
				this.Graph.DrawPathAbs(path, drawSegment ? color : Color.Transparent, point.BackHatchStyle, point.BackImage, point.BackImageWrapMode, point.BackImageTransparentColor, point.BackImageAlignment, point.BackGradientStyle, drawSegment ? point.BackSecondaryColor : Color.Transparent, drawSegment ? point.BorderColor : Color.Transparent, point.BorderWidth, point.BorderDashStyle, PenAlignment.Center, drawSegmentShadow ? point.series.ShadowOffset : 0, point.series.ShadowColor);
			}
			if (this.Common.ProcessModeRegions)
			{
				this.Common.HotRegionsList.AddHotRegion(path, false, this.Graph, point, point.series.Name, pointIndex);
			}
			path.Dispose();
			path = new GraphicsPath();
			if (startWidth > 0f)
			{
				path.AddLine(num3 + (startWidth / 2f), location, num3, location + num);
			}
			path.AddLine(num3, location + num, num3, (location + height) + num2);
			if (endWidth > 0f)
			{
				path.AddLine(num3, (location + height) + num2, num3 + (endWidth / 2f), location + height);
			}
			path.AddLine(num3 + (endWidth / 2f), location + height, num3 + (startWidth / 2f), location);
			if (this.Common.ProcessModePaint)
			{
				this.Graph.DrawPathAbs(path, drawSegment ? color2 : Color.Transparent, point.BackHatchStyle, point.BackImage, point.BackImageWrapMode, point.BackImageTransparentColor, point.BackImageAlignment, point.BackGradientStyle, drawSegment ? point.BackSecondaryColor : Color.Transparent, drawSegment ? point.BorderColor : Color.Transparent, point.BorderWidth, point.BorderDashStyle, PenAlignment.Center, drawSegmentShadow ? point.series.ShadowOffset : 0, point.series.ShadowColor);
			}
			if (this.Common.ProcessModeRegions)
			{
				this.Common.HotRegionsList.AddHotRegion(path, false, this.Graph, point, point.series.Name, pointIndex);
			}
			path.Dispose();
			if (((this._rotation3D > 0f) && (startWidth > 0f)) && (nothingOnTop && this.Area.Area3DStyle.Enable3D))
			{
				PointF[] points = new PointF[] { new PointF(num3 + (startWidth / 2f), location), new PointF(num3, location + num), new PointF(num3 - (startWidth / 2f), location), new PointF(num3, location - num) };
				GraphicsPath path2 = new GraphicsPath();
				path2.AddLines(points);
				path2.CloseAllFigures();
				if (this.Common.ProcessModePaint)
				{
					this.Graph.DrawPathAbs(path2, drawSegment ? ChartGraphics.GetGradientColor(point.Color, Color.Black, 0.4) : Color.Transparent, point.BackHatchStyle, point.BackImage, point.BackImageWrapMode, point.BackImageTransparentColor, point.BackImageAlignment, point.BackGradientStyle, drawSegment ? point.BackSecondaryColor : Color.Transparent, drawSegment ? point.BorderColor : Color.Transparent, point.BorderWidth, point.BorderDashStyle, PenAlignment.Center, drawSegmentShadow ? point.series.ShadowOffset : 0, point.series.ShadowColor);
				}
				if (this.Common.ProcessModeRegions)
				{
					this.Common.HotRegionsList.AddHotRegion(path2, false, this.Graph, point, point.series.Name, pointIndex);
				}
				path2.Dispose();
			}
			if (((this._rotation3D < 0f) && (startWidth > 0f)) && (nothingOnBottom && this.Area.Area3DStyle.Enable3D))
			{
				PointF[] tfArray2 = new PointF[] { new PointF(num3 + (endWidth / 2f), location + height), new PointF(num3, (location + height) + num2), new PointF(num3 - (endWidth / 2f), location + height), new PointF(num3, (location + height) - num2) };
				GraphicsPath path3 = new GraphicsPath();
				path3.AddLines(tfArray2);
				path3.CloseAllFigures();
				if (this.Common.ProcessModePaint)
				{
					this.Graph.DrawPathAbs(path3, drawSegment ? ChartGraphics.GetGradientColor(point.Color, Color.Black, 0.4) : Color.Transparent, point.BackHatchStyle, point.BackImage, point.BackImageWrapMode, point.BackImageTransparentColor, point.BackImageAlignment, point.BackGradientStyle, drawSegment ? point.BackSecondaryColor : Color.Transparent, drawSegment ? point.BorderColor : Color.Transparent, point.BorderWidth, point.BorderDashStyle, PenAlignment.Center, drawSegmentShadow ? point.series.ShadowOffset : 0, point.series.ShadowColor);
				}
				if (this.Common.ProcessModeRegions)
				{
					this.Common.HotRegionsList.AddHotRegion(path3, false, this.Graph, point, point.series.Name, pointIndex);
				}
				path3.Dispose();
			}
			this.Graph.EndHotRegion();
		}

		private void DrawFunnelCircularSegment(DataPoint point, int pointIndex, float startWidth, float endWidth, float location, float height, bool nothingOnTop, bool nothingOnBottom, bool drawSegment, bool drawSegmentShadow)
		{
			PointF empty = PointF.Empty;
			PointF rightSideLinePoint = PointF.Empty;
			if (this.Area.Area3DStyle.Enable3D && !this.round3DShape)
			{
				this.DrawFunnel3DSquareSegment(point, pointIndex, startWidth, endWidth, location, height, nothingOnTop, nothingOnBottom, drawSegment, drawSegmentShadow);
				return;
			}
			if (!nothingOnBottom)
			{
				height += 0.3f;
			}
			float num = startWidth;
			float num2 = endWidth;
			if ((this._funnelStyle == FunnelStyle.YIsHeight) && !this.isPyramid)
			{
				if (startWidth < this._funnelNeckSize.Width)
				{
					startWidth = this._funnelNeckSize.Width;
				}
				if (endWidth < this._funnelNeckSize.Width)
				{
					endWidth = this._funnelNeckSize.Width;
				}
			}
			float tension = 0.8f;
			float num4 = (float)((startWidth / 2f) * Math.Sin((((float)this._rotation3D) / 180f) * 3.1415926535897931));
			float num5 = (float)((endWidth / 2f) * Math.Sin((((float)this._rotation3D) / 180f) * 3.1415926535897931));
			RectangleF absoluteRectangle = this.Graph.GetAbsoluteRectangle(this.PlotAreaPosition);
			float x = absoluteRectangle.X + (absoluteRectangle.Width / 2f);
			this.Graph.StartHotRegion(point);
			GraphicsPath resultPath = new GraphicsPath();
			if (startWidth > 0f)
			{
				if (this.Area.Area3DStyle.Enable3D)
				{
					PointF[] points = new PointF[] { new PointF(x + (startWidth / 2f), location), new PointF(x, location + num4), new PointF(x - (startWidth / 2f), location), new PointF(x, location - num4) };
					GraphicsPath ellipseFlattenPath = new GraphicsPath();
					ellipseFlattenPath.AddClosedCurve(points, tension);
					ellipseFlattenPath.Flatten();
					ellipseFlattenPath.Reverse();
					this.Graph.AddEllipseSegment(resultPath, ellipseFlattenPath, null, true, 0f, out empty, out rightSideLinePoint);
				}
				else
				{
					resultPath.AddLine(x - (startWidth / 2f), location, x + (startWidth / 2f), location);
				}
			}
			if (((this._funnelStyle == FunnelStyle.YIsHeight) && !this.isPyramid) && ((startWidth > this._funnelNeckSize.Width) && (endWidth <= this._funnelNeckSize.Width)))
			{
				PointF tf3 = ChartGraphics.GetLinesIntersection(x + (this._funnelNeckSize.Width / 2f), absoluteRectangle.Top, x + (this._funnelNeckSize.Width / 2f), absoluteRectangle.Bottom, x + (num / 2f), location, x + (num2 / 2f), location + height);
				tf3.Y = absoluteRectangle.Bottom - this._funnelNeckSize.Height;
				resultPath.AddLine(x + (startWidth / 2f), location, tf3.X, tf3.Y);
				resultPath.AddLine(tf3.X, tf3.Y, tf3.X, location + height);
			}
			else
			{
				resultPath.AddLine(x + (startWidth / 2f), location, x + (endWidth / 2f), location + height);
			}
			if (endWidth > 0f)
			{
				if (this.Area.Area3DStyle.Enable3D)
				{
					PointF[] tfArray2 = new PointF[] { new PointF(x + (endWidth / 2f), location + height), new PointF(x, (location + height) + num5), new PointF(x - (endWidth / 2f), location + height), new PointF(x, (location + height) - num5) };
					GraphicsPath path3 = new GraphicsPath();
					path3.AddClosedCurve(tfArray2, tension);
					path3.Flatten();
					path3.Reverse();
					using (GraphicsPath path4 = new GraphicsPath())
					{
						this.Graph.AddEllipseSegment(path4, path3, null, true, 0f, out empty, out rightSideLinePoint);
						path4.Reverse();
						if (path4.PointCount > 0)
						{
							resultPath.AddPath(path4, false);
						}
						goto Label_0468;
					}
				}
				resultPath.AddLine((float)(x + (endWidth / 2f)), (float)(location + height), (float)(x - (endWidth / 2f)), (float)(location + height));
			}
		Label_0468:
			if (((this._funnelStyle == FunnelStyle.YIsHeight) && !this.isPyramid) && ((startWidth > this._funnelNeckSize.Width) && (endWidth <= this._funnelNeckSize.Width)))
			{
				PointF tf4 = ChartGraphics.GetLinesIntersection(x - (this._funnelNeckSize.Width / 2f), absoluteRectangle.Top, x - (this._funnelNeckSize.Width / 2f), absoluteRectangle.Bottom, x - (num / 2f), location, x - (num2 / 2f), location + height);
				tf4.Y = absoluteRectangle.Bottom - this._funnelNeckSize.Height;
				resultPath.AddLine(tf4.X, location + height, tf4.X, tf4.Y);
				resultPath.AddLine(tf4.X, tf4.Y, x - (startWidth / 2f), location);
			}
			else
			{
				resultPath.AddLine(x - (endWidth / 2f), location + height, x - (startWidth / 2f), location);
			}
			if (this.Common.ProcessModePaint)
			{
				if (this.Area.Area3DStyle.Enable3D && (this.Graph.ActiveRenderingType == RenderingType.Gdi))
				{
					Color color = ChartGraphics.GetGradientColor(point.Color, Color.White, 0.3);
					Color color2 = ChartGraphics.GetGradientColor(point.Color, Color.Black, 0.3);
					RectangleF bounds = resultPath.GetBounds();
					if (bounds.Width == 0f)
					{
						bounds.Width = 1f;
					}
					if (bounds.Height == 0f)
					{
						bounds.Height = 1f;
					}
					using (LinearGradientBrush brush = new LinearGradientBrush(bounds, color, color2, 0f))
					{
						ColorBlend blend = new ColorBlend(5);
						blend.Colors[0] = color2;
						blend.Colors[1] = color2;
						blend.Colors[2] = color;
						blend.Colors[3] = color2;
						blend.Colors[4] = color2;
						blend.Positions[0] = 0f;
						blend.Positions[1] = 0f;
						blend.Positions[2] = 0.5f;
						blend.Positions[3] = 1f;
						blend.Positions[4] = 1f;
						brush.InterpolationColors = blend;
						this.Graph.Graphics.FillPath(brush, resultPath);
						Pen pen = new Pen(point.BorderColor, (float)point.BorderWidth);
						pen.DashStyle = this.Graph.GetPenStyle(point.BorderDashStyle);
						if (((point.BorderWidth == 0) || (point.BorderDashStyle == ChartDashStyle.NotSet)) || (point.BorderColor == Color.Empty))
						{
							pen = new Pen(ChartGraphics.GetGradientColor(point.Color, Color.Black, 0.3), 1f);
							pen.Alignment = PenAlignment.Inset;
						}
						pen.StartCap = LineCap.Round;
						pen.EndCap = LineCap.Round;
						pen.LineJoin = LineJoin.Bevel;
						this.Graph.DrawPath(pen, resultPath);
						pen.Dispose();
						goto Label_084B;
					}
				}
				this.Graph.DrawPathAbs(resultPath, drawSegment ? point.Color : Color.Transparent, point.BackHatchStyle, point.BackImage, point.BackImageWrapMode, point.BackImageTransparentColor, point.BackImageAlignment, point.BackGradientStyle, drawSegment ? point.BackSecondaryColor : Color.Transparent, drawSegment ? point.BorderColor : Color.Transparent, point.BorderWidth, point.BorderDashStyle, PenAlignment.Center, drawSegmentShadow ? point.series.ShadowOffset : 0, point.series.ShadowColor);
			}
		Label_084B:
			if (this.Common.ProcessModeRegions)
			{
				this.Common.HotRegionsList.AddHotRegion(resultPath, false, this.Graph, point, point.series.Name, pointIndex);
			}
			resultPath.Dispose();
			if (((this._rotation3D > 0f) && (startWidth > 0f)) && (nothingOnTop && this.Area.Area3DStyle.Enable3D))
			{
				PointF[] tfArray3 = new PointF[] { new PointF(x + (startWidth / 2f), location), new PointF(x, location + num4), new PointF(x - (startWidth / 2f), location), new PointF(x, location - num4) };
				GraphicsPath path = new GraphicsPath();
				path.AddClosedCurve(tfArray3, tension);
				if (this.Common.ProcessModePaint)
				{
					this.Graph.DrawPathAbs(path, drawSegment ? ChartGraphics.GetGradientColor(point.Color, Color.Black, 0.4) : Color.Transparent, point.BackHatchStyle, point.BackImage, point.BackImageWrapMode, point.BackImageTransparentColor, point.BackImageAlignment, point.BackGradientStyle, drawSegment ? point.BackSecondaryColor : Color.Transparent, drawSegment ? point.BorderColor : Color.Transparent, point.BorderWidth, point.BorderDashStyle, PenAlignment.Center, drawSegmentShadow ? point.series.ShadowOffset : 0, point.series.ShadowColor);
				}
				if (this.Common.ProcessModeRegions)
				{
					this.Common.HotRegionsList.AddHotRegion(path, false, this.Graph, point, point.series.Name, pointIndex);
				}
				path.Dispose();
			}
			if (((this._rotation3D < 0f) && (startWidth > 0f)) && (nothingOnBottom && this.Area.Area3DStyle.Enable3D))
			{
				PointF[] tfArray4 = new PointF[] { new PointF(x + (endWidth / 2f), location + height), new PointF(x, (location + height) + num5), new PointF(x - (endWidth / 2f), location + height), new PointF(x, (location + height) - num5) };
				GraphicsPath path6 = new GraphicsPath();
				path6.AddClosedCurve(tfArray4, tension);
				if (this.Common.ProcessModePaint)
				{
					this.Graph.DrawPathAbs(path6, drawSegment ? ChartGraphics.GetGradientColor(point.Color, Color.Black, 0.4) : Color.Transparent, point.BackHatchStyle, point.BackImage, point.BackImageWrapMode, point.BackImageTransparentColor, point.BackImageAlignment, point.BackGradientStyle, drawSegment ? point.BackSecondaryColor : Color.Transparent, drawSegment ? point.BorderColor : Color.Transparent, point.BorderWidth, point.BorderDashStyle, PenAlignment.Center, drawSegmentShadow ? point.series.ShadowOffset : 0, point.series.ShadowColor);
				}
				if (this.Common.ProcessModeRegions)
				{
					this.Common.HotRegionsList.AddHotRegion(path6, false, this.Graph, point, point.series.Name, pointIndex);
				}
				path6.Dispose();
			}
			this.Graph.EndHotRegion();
		}

		private void DrawLabels()
		{
			foreach (FunnelPointLabelInfo info in this.labelInfoList)
			{
				if (((info.Position.IsEmpty || float.IsNaN(info.Position.X)) || (float.IsNaN(info.Position.Y) || float.IsNaN(info.Position.Width))) || float.IsNaN(info.Position.Height))
				{
					continue;
				}
				this.Graph.StartHotRegion(info.Point);
				SizeF ef = this.Graph.MeasureString("W", info.Point.Font, new SizeF(1000f, 1000f), StringFormat.GenericTypographic);
				if (((!info.CalloutPoint1.IsEmpty && !info.CalloutPoint2.IsEmpty) && (!float.IsNaN(info.CalloutPoint1.X) && !float.IsNaN(info.CalloutPoint1.Y))) && (!float.IsNaN(info.CalloutPoint2.X) && !float.IsNaN(info.CalloutPoint2.Y)))
				{
					if (info.OutsidePlacement == FunnelLabelPlacement.Right)
					{
						info.CalloutPoint2.X -= ef.Width / 2f;
						info.CalloutPoint1.X += 2f;
					}
					else
					{
						info.CalloutPoint2.X += ef.Width / 2f;
						info.CalloutPoint1.X += 2f;
					}
					Color calloutLineColor = this.GetCalloutLineColor(info.Point);
					this.Graph.DrawLineAbs(calloutLineColor, 1, ChartDashStyle.Solid, info.CalloutPoint1, info.CalloutPoint2);
				}
				RectangleF position = info.Position;
				position.Inflate(ef.Width / 2f, ef.Height / 8f);
				position = this.Graph.GetRelativeRectangle(position);
				using (StringFormat format = new StringFormat())
				{
					format.Alignment = StringAlignment.Center;
					format.LineAlignment = StringAlignment.Center;
					using (Brush brush = new SolidBrush(info.Point.LabelForeColor))
					{
						this.Graph.DrawPointLabelStringRel(this.Common, info.Text, info.Point.Font, brush, position, format, info.Point.LabelAngle, position, info.Point.LabelBackColor, info.Point.LabelBorderColor, info.Point.LabelBorderWidth, info.Point.LabelBorderDashStyle, info.Point.series, info.Point, info.PointIndex);
					}
					this.Graph.EndHotRegion();
					continue;
				}
			}
		}

		private bool FitPointLabels()
		{
			RectangleF absoluteRectangle = this.Graph.GetAbsoluteRectangle(this.PlotAreaPosition);
			absoluteRectangle.Inflate(-4f, -4f);
			this.GetLabelsPosition();
			RectangleF rectangle = this.Graph.GetAbsoluteRectangle(new RectangleF(1f, 1f, 1f, 1f));
			foreach (FunnelPointLabelInfo info in this.labelInfoList)
			{
				RectangleF position = info.Position;
				if ((info.Style == FunnelLabelStyle.Outside) || (info.Style == FunnelLabelStyle.OutsideInColumn))
				{
					float num = 10f;
					if (info.OutsidePlacement == FunnelLabelPlacement.Right)
					{
						position.Width += num;
					}
					else if (info.OutsidePlacement == FunnelLabelPlacement.Left)
					{
						position.X -= num;
						position.Width += num;
					}
				}
				if (info.Style != FunnelLabelStyle.Inside)
				{
					if ((absoluteRectangle.X - position.X) > rectangle.X)
					{
						rectangle.X = absoluteRectangle.X - position.X;
					}
					if ((position.Right - absoluteRectangle.Right) > rectangle.Width)
					{
						rectangle.Width = position.Right - absoluteRectangle.Right;
					}
				}
				if ((absoluteRectangle.Y - position.Y) > rectangle.Y)
				{
					rectangle.Y = absoluteRectangle.Y - position.Y;
				}
				if ((position.Bottom - absoluteRectangle.Bottom) > rectangle.Height)
				{
					rectangle.Height = position.Bottom - absoluteRectangle.Bottom;
				}
			}
			rectangle = this.Graph.GetRelativeRectangle(rectangle);
			if (((rectangle.X <= 1f) && (rectangle.Y <= 1f)) && ((rectangle.Width <= 1f) && (rectangle.Height <= 1f)))
			{
				return true;
			}
			this.plotAreaSpacing = rectangle;
			this.PlotAreaPosition = this.GetPlotAreaPosition();
			this.segmentList = this.GetFunnelSegmentPositions();
			this.GetLabelsPosition();
			return false;
		}

		private Color GetCalloutLineColor(DataPointCustomProperties properties)
		{
			Color black = Color.Black;
			string text = properties["CalloutLineColor"];
			if ((text != null) && (text.Length > 0))
			{
				bool flag = false;
				ColorConverter converter = new ColorConverter();
				try
				{
					black = (Color)converter.ConvertFromInvariantString(text);
				}
				catch (ArgumentException)
				{
					flag = true;
				}
				catch (NotSupportedException)
				{
					flag = true;
				}
				if (!flag)
				{
					return black;
				}
				try
				{
					black = (Color)converter.ConvertFromString(text);
				}
				catch (ArgumentException)
				{
					throw new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid(text, "CalloutLineColor"));
				}
			}
			return black;
		}

		private void GetDataPointValuesStatistic()
		{
			Series dataSeries = this.GetDataSeries();
			if (dataSeries != null)
			{
				this.yValueTotal = 0.0;
				this._xValueTotal = 0.0;
				this._yValueMax = 0.0;
				this.pointNumber = 0;
				this._valuePercentages = null;
				if (this.GetPyramidValueType(dataSeries) == PyramidValueType.Surface)
				{
					double num = 0.0;
					int pointIndex = 0;
					foreach (DataPoint point in dataSeries.Points)
					{
						if (!point.IsEmpty)
						{
							num += this.GetYValue(point, pointIndex);
						}
						pointIndex++;
					}
					double num3 = 100.0;
					double num4 = (2.0 * num) / num3;
					double num5 = num4 / num3;
					double[] numArray = new double[dataSeries.Points.Count];
					double num6 = 0.0;
					for (int i = 0; i < numArray.Length; i++)
					{
						double yValue = this.GetYValue(dataSeries.Points[i], i);
						num6 += yValue;
						numArray[i] = Math.Sqrt((2.0 * num6) / num5);
					}
					this._valuePercentages = numArray;
				}
				foreach (DataPoint point2 in dataSeries.Points)
				{
					if (!point2.IsEmpty)
					{
						double num9 = this.GetYValue(point2, this.pointNumber);
						this.yValueTotal += num9;
						this._yValueMax = Math.Max(this._yValueMax, num9);
						this._xValueTotal += this.GetXValue(point2);
					}
					this.pointNumber++;
				}
			}
		}

		private Series GetDataSeries()
		{
			if (this._chartTypeSeries == null)
			{
				Series series = null;
				foreach (Series series2 in this.Common.DataManager.Series)
				{
					if (series2.IsVisible() && (series2.ChartArea == this.Area.Name))
					{
						if (string.Compare(series2.ChartTypeName, this.Name, true, CultureInfo.CurrentCulture) == 0)
						{
							if (series == null)
							{
								series = series2;
							}
						}
						else if (!this.Common.ChartPicture.SuppressExceptions)
						{
							throw new InvalidOperationException(SR.ExceptionFunnelCanNotCombine);
						}
					}
				}
				this._chartTypeSeries = series;
			}
			return this._chartTypeSeries;
		}

		private Funnel3DDrawingStyle GetFunnel3DDrawingStyle(DataPointCustomProperties properties)
		{
			Funnel3DDrawingStyle style = this.isPyramid ? Funnel3DDrawingStyle.SquareBase : Funnel3DDrawingStyle.CircularBase;
			string str = properties[this.funnel3DDrawingStyleAttributeName];
			if ((str != null) && (str.Length > 0))
			{
				try
				{
					style = (Funnel3DDrawingStyle)Enum.Parse(typeof(Funnel3DDrawingStyle), str, true);
				}
				catch
				{
					throw new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid(str, this.funnel3DDrawingStyleAttributeName));
				}
			}
			return style;
		}

		private void GetFunnelMinPointHeight(DataPointCustomProperties properties)
		{
			this._funnelMinPointHeight = 0f;
			string s = properties[this.funnelPointMinHeight];
			if ((s != null) && (s.Length > 0))
			{
				float num;
				bool flag = float.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out num);
				if (flag)
				{
					this._funnelMinPointHeight = num;
				}
				if ((!flag || (this._funnelMinPointHeight < 0f)) || (this._funnelMinPointHeight > 100f))
				{
					throw new InvalidOperationException(SR.ExceptionFunnelMinimumPointHeightAttributeInvalid);
				}
				this._funnelMinPointHeight = (float)((this.yValueTotal * this._funnelMinPointHeight) / 100.0);
				this.GetDataPointValuesStatistic();
			}
		}

		private SizeF GetFunnelNeckSize(DataPointCustomProperties properties)
		{
			SizeF size = new SizeF(5f, 5f);
			string s = properties["FunnelNeckWidth"];
			if ((s != null) && (s.Length > 0))
			{
				float num;
				bool flag = float.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out num);
				if (flag)
				{
					size.Width = num;
				}
				if ((!flag || (size.Width < 0f)) || (size.Width > 100f))
				{
					throw new InvalidOperationException(SR.ExceptionFunnelNeckWidthInvalid);
				}
			}
			s = properties["FunnelNeckHeight"];
			if ((s != null) && (s.Length > 0))
			{
				float num2;
				bool flag2 = float.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out num2);
				if (flag2)
				{
					size.Height = num2;
				}
				if ((!flag2 || (size.Height < 0f)) || (size.Height > 100f))
				{
					throw new InvalidOperationException(SR.ExceptionFunnelNeckHeightInvalid);
				}
			}
			if (size.Height > (this.PlotAreaPosition.Height / 2f))
			{
				size.Height = this.PlotAreaPosition.Height / 2f;
			}
			if (size.Width > (this.PlotAreaPosition.Width / 2f))
			{
				size.Width = this.PlotAreaPosition.Width / 2f;
			}
			return this.Graph.GetAbsoluteSize(size);
		}

		private float GetFunnelPointGap(DataPointCustomProperties properties)
		{
			float num2;
			float width = 0f;
			string s = properties[this.funnelPointGapAttributeName];
			if ((s == null) || (s.Length <= 0))
			{
				return width;
			}
			if (!float.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out num2))
			{
				throw new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid(s, this.funnelPointGapAttributeName));
			}
			width = num2;
			float num3 = this.PlotAreaPosition.Height / ((float)(this.pointNumber - (this.ShouldDrawFirstPoint() ? 1 : 2)));
			if (width > num3)
			{
				width = num3;
			}
			if (width < 0f)
			{
				width = 0f;
			}
			return this.Graph.GetAbsoluteSize(new SizeF(width, width)).Height;
		}

		private int GetFunnelRotation(DataPointCustomProperties properties)
		{
			int num = 5;
			string s = properties[this.funnelRotationAngleAttributeName];
			if ((s != null) && (s.Length > 0))
			{
				int num2;
				bool flag = int.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out num2);
				if (flag)
				{
					num = num2;
				}
				if ((!flag || (num < -10)) || (num > 10))
				{
					throw new InvalidOperationException(SR.ExceptionFunnelAngleRangeInvalid);
				}
			}
			return num;
		}

		private ArrayList GetFunnelSegmentPositions()
		{
			ArrayList list = new ArrayList();
			Series dataSeries = this.GetDataSeries();
			if (dataSeries != null)
			{
				this._funnelStyle = this.GetFunnelStyle(dataSeries);
				this.round3DShape = this.GetFunnel3DDrawingStyle(dataSeries) == Funnel3DDrawingStyle.CircularBase;
				this.funnelSegmentGap = this.GetFunnelPointGap(dataSeries);
				this._funnelNeckSize = this.GetFunnelNeckSize(dataSeries);
				float y = this.Graph.GetAbsolutePoint(this.PlotAreaPosition.Location).Y;
				if (this.isPyramid)
				{
					y = this.Graph.GetAbsoluteRectangle(this.PlotAreaPosition).Bottom;
				}
				for (int i = 0; (i >= 0) && (i < dataSeries.Points.Count); i++)
				{
					DataPoint point = dataSeries.Points[i];
					if ((i > 0) || this.ShouldDrawFirstPoint())
					{
						float startWidth = 0f;
						float endWidth = 0f;
						float height = 0f;
						this.GetPointWidthAndHeight(dataSeries, i, y, out height, out startWidth, out endWidth);
						bool flag = false;
						bool flag2 = false;
						if (this.funnelSegmentGap > 0f)
						{
							flag = true;
							flag2 = true;
						}
						else
						{
							if (this.ShouldDrawFirstPoint())
							{
								if ((i == 0) || (dataSeries.Points[i - 1].Color.A != 0xff))
								{
									if (this.isPyramid)
									{
										flag2 = true;
									}
									else
									{
										flag = true;
									}
								}
							}
							else if ((i == 1) || (dataSeries.Points[i - 1].Color.A != 0xff))
							{
								if (this.isPyramid)
								{
									flag2 = true;
								}
								else
								{
									flag = true;
								}
							}
							if (i == (dataSeries.Points.Count - 1))
							{
								if (this.isPyramid)
								{
									flag = true;
								}
								else
								{
									flag2 = true;
								}
							}
							else if (dataSeries.Points[i + 1].Color.A != 0xff)
							{
								if (this.isPyramid)
								{
									flag = true;
								}
								else
								{
									flag2 = true;
								}
							}
						}
						FunnelSegmentInfo info = new FunnelSegmentInfo();
						info.Point = point;
						info.PointIndex = i;
						info.StartWidth = startWidth;
						info.EndWidth = endWidth;
						info.Location = this.isPyramid ? (y - height) : y;
						info.Height = height;
						info.NothingOnTop = flag;
						info.NothingOnBottom = flag2;
						list.Add(info);
						if (this.isPyramid)
						{
							y -= height + this.funnelSegmentGap;
						}
						else
						{
							y += height + this.funnelSegmentGap;
						}
					}
				}
			}
			return list;
		}

		private FunnelStyle GetFunnelStyle(DataPointCustomProperties properties)
		{
			FunnelStyle yIsHeight = FunnelStyle.YIsHeight;
			if (!this.isPyramid)
			{
				string str = properties["FunnelStyle"];
				if ((str == null) || (str.Length <= 0))
				{
					return yIsHeight;
				}
				try
				{
					yIsHeight = (FunnelStyle)Enum.Parse(typeof(FunnelStyle), str, true);
				}
				catch
				{
					throw new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid(str, "FunnelStyle"));
				}
			}
			return yIsHeight;
		}

		public virtual Image GetImage(ChartTypeRegistry registry)
		{
			return (Image)registry.ResourceManager.GetObject(this.Name + "ChartType");
		}

		private FunnelLabelVerticalAlignment GetInsideLabelAlignment(DataPointCustomProperties properties)
		{
			FunnelLabelVerticalAlignment center = FunnelLabelVerticalAlignment.Center;
			string str = properties[this.funnelInsideLabelAlignmentAttributeName];
			if ((str != null) && (str.Length > 0))
			{
				try
				{
					center = (FunnelLabelVerticalAlignment)Enum.Parse(typeof(FunnelLabelVerticalAlignment), str, true);
				}
				catch
				{
					throw new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid(str, this.funnelInsideLabelAlignmentAttributeName));
				}
			}
			return center;
		}

		private void GetLabelsPosition()
		{
			RectangleF absoluteRectangle = this.Graph.GetAbsoluteRectangle(this.PlotAreaPosition);
			float num = absoluteRectangle.X + (absoluteRectangle.Width / 2f);
			SizeF ef2 = new SizeF(3f, 3f);
			foreach (FunnelPointLabelInfo info in this.labelInfoList)
			{
				bool flag = false;
				int count = info.PointIndex + (this.ShouldDrawFirstPoint() ? 0 : 1);
				if ((count > this.segmentList.Count) && !this.ShouldDrawFirstPoint())
				{
					count = this.segmentList.Count;
					flag = true;
				}
				FunnelSegmentInfo info2 = null;
				foreach (FunnelSegmentInfo info3 in this.segmentList)
				{
					if (info3.PointIndex == count)
					{
						info2 = info3;
						break;
					}
				}
				if (info2 != null)
				{
					info.Position.Width = info.Size.Width;
					info.Position.Height = info.Size.Height;
					if ((info.Style == FunnelLabelStyle.Outside) || (info.Style == FunnelLabelStyle.OutsideInColumn))
					{
						if (this._funnelStyle == FunnelStyle.YIsHeight)
						{
							float startWidth = info2.StartWidth;
							float endWidth = info2.EndWidth;
							if (!this.isPyramid)
							{
								if (startWidth < this._funnelNeckSize.Width)
								{
									startWidth = this._funnelNeckSize.Width;
								}
								if (endWidth < this._funnelNeckSize.Width)
								{
									endWidth = this._funnelNeckSize.Width;
								}
								if ((info2.StartWidth >= this._funnelNeckSize.Width) && (info2.EndWidth < this._funnelNeckSize.Width))
								{
									endWidth = info2.EndWidth;
								}
							}
							info.Position.Y = (info2.Location + (info2.Height / 2f)) - (info.Size.Height / 2f);
							if (info.Style == FunnelLabelStyle.OutsideInColumn)
							{
								if (info.OutsidePlacement == FunnelLabelPlacement.Right)
								{
									info.Position.X = absoluteRectangle.Right + (4f * ef2.Width);
									if (!this.isPyramid)
									{
										info.CalloutPoint1.X = num + Math.Max((float)(this._funnelNeckSize.Width / 2f), (float)((startWidth + endWidth) / 4f));
									}
									else
									{
										info.CalloutPoint1.X = num + ((startWidth + endWidth) / 4f);
									}
									info.CalloutPoint2.X = info.Position.X;
								}
								else
								{
									info.Position.X = (absoluteRectangle.X - info.Size.Width) - (4f * ef2.Width);
									if (!this.isPyramid)
									{
										info.CalloutPoint1.X = num - Math.Max((float)(this._funnelNeckSize.Width / 2f), (float)((startWidth + endWidth) / 4f));
									}
									else
									{
										info.CalloutPoint1.X = num - ((startWidth + endWidth) / 4f);
									}
									info.CalloutPoint2.X = info.Position.Right;
								}
								info.CalloutPoint1.Y = info2.Location + (info2.Height / 2f);
								info.CalloutPoint2.Y = info.CalloutPoint1.Y;
							}
							else if (info.OutsidePlacement == FunnelLabelPlacement.Right)
							{
								info.Position.X = (num + ((startWidth + endWidth) / 4f)) + (4f * ef2.Width);
							}
							else
							{
								info.Position.X = ((num - info.Size.Width) - ((startWidth + endWidth) / 4f)) - (4f * ef2.Width);
							}
						}
						else
						{
							if (flag)
							{
								if (info.OutsidePlacement == FunnelLabelPlacement.Right)
								{
									info.Position.X = (num + (info2.EndWidth / 2f)) + (4f * ef2.Width);
								}
								else
								{
									info.Position.X = ((num - info.Size.Width) - (info2.EndWidth / 2f)) - (4f * ef2.Width);
								}
								info.Position.Y = (info2.Location + info2.Height) - (info.Size.Height / 2f);
							}
							else
							{
								if (info.OutsidePlacement == FunnelLabelPlacement.Right)
								{
									info.Position.X = (num + (info2.StartWidth / 2f)) + (4f * ef2.Width);
								}
								else
								{
									info.Position.X = ((num - info.Size.Width) - (info2.StartWidth / 2f)) - (4f * ef2.Width);
								}
								info.Position.Y = info2.Location - (info.Size.Height / 2f);
							}
							if (info.Style == FunnelLabelStyle.OutsideInColumn)
							{
								if (info.OutsidePlacement == FunnelLabelPlacement.Right)
								{
									info.Position.X = absoluteRectangle.Right + (4f * ef2.Width);
									info.CalloutPoint1.X = num + ((flag ? info2.EndWidth : info2.StartWidth) / 2f);
									info.CalloutPoint2.X = info.Position.X;
								}
								else
								{
									info.Position.X = (absoluteRectangle.X - info.Size.Width) - (4f * ef2.Width);
									info.CalloutPoint1.X = num - ((flag ? info2.EndWidth : info2.StartWidth) / 2f);
									info.CalloutPoint2.X = info.Position.Right;
								}
								info.CalloutPoint1.Y = info2.Location;
								if (flag)
								{
									info.CalloutPoint1.Y += info2.Height;
								}
								info.CalloutPoint2.Y = info.CalloutPoint1.Y;
							}
						}
					}
					else if (info.Style == FunnelLabelStyle.Inside)
					{
						info.Position.X = num - (info.Size.Width / 2f);
						if (this._funnelStyle == FunnelStyle.YIsHeight)
						{
							info.Position.Y = (info2.Location + (info2.Height / 2f)) - (info.Size.Height / 2f);
							if (info.VerticalAlignment == FunnelLabelVerticalAlignment.Top)
							{
								info.Position.Y -= ((info2.Height / 2f) - (info.Size.Height / 2f)) - ef2.Height;
							}
							else if (info.VerticalAlignment == FunnelLabelVerticalAlignment.Bottom)
							{
								info.Position.Y += ((info2.Height / 2f) - (info.Size.Height / 2f)) - ef2.Height;
							}
						}
						else
						{
							info.Position.Y = info2.Location - (info.Size.Height / 2f);
							if (info.VerticalAlignment == FunnelLabelVerticalAlignment.Top)
							{
								info.Position.Y -= (info.Size.Height / 2f) + ef2.Height;
							}
							else if (info.VerticalAlignment == FunnelLabelVerticalAlignment.Bottom)
							{
								info.Position.Y += (info.Size.Height / 2f) + ef2.Height;
							}
							if (flag)
							{
								info.Position.Y += info2.Height;
							}
						}
						if (this.Area.Area3DStyle.Enable3D)
						{
							info.Position.Y += (float)(((info2.EndWidth + info2.StartWidth) / 4f) * Math.Sin((((float)this._rotation3D) / 180f) * 3.1415926535897931));
						}
					}
					for (int i = 0; this.IsLabelsOverlap(info) && (i < 0x3e8); i++)
					{
						float num6 = this.isPyramid ? -3f : 3f;
						info.Position.Y += num6;
						if (!info.CalloutPoint2.IsEmpty)
						{
							info.CalloutPoint2.Y += num6;
						}
					}
				}
			}
		}

		private FunnelLabelStyle GetLabelStyle(DataPointCustomProperties properties)
		{
			FunnelLabelStyle outsideInColumn = FunnelLabelStyle.OutsideInColumn;
			string str = properties[this.funnelLabelStyleAttributeName];
			if ((str != null) && (str.Length > 0))
			{
				try
				{
					outsideInColumn = (FunnelLabelStyle)Enum.Parse(typeof(FunnelLabelStyle), str, true);
				}
				catch
				{
					throw new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid(outsideInColumn.ToString(), this.funnelLabelStyleAttributeName));
				}
			}
			return outsideInColumn;
		}

		public virtual LegendImageStyle GetLegendImageStyle(Series series)
		{
			return LegendImageStyle.Rectangle;
		}

		private FunnelLabelPlacement GetOutsideLabelPlacement(DataPointCustomProperties properties)
		{
			FunnelLabelPlacement right = FunnelLabelPlacement.Right;
			string str = properties[this.funnelOutsideLabelPlacementAttributeName];
			if ((str != null) && (str.Length > 0))
			{
				try
				{
					right = (FunnelLabelPlacement)Enum.Parse(typeof(FunnelLabelPlacement), str, true);
				}
				catch
				{
					throw new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid(str, this.funnelOutsideLabelPlacementAttributeName));
				}
			}
			return right;
		}

		private RectangleF GetPlotAreaPosition()
		{
			RectangleF rectangle = this.Area.InnerPlotPosition.Auto ? this.Area.Position.ToRectangleF() : this.Area.PlotAreaPosition.ToRectangleF();
			if (this.plotAreaSpacing.Y > (rectangle.Height / 2f))
			{
				this.plotAreaSpacing.Y = rectangle.Height / 2f;
			}
			if (this.plotAreaSpacing.Height > (rectangle.Height / 2f))
			{
				this.plotAreaSpacing.Height = rectangle.Height / 2f;
			}
			rectangle.X += this.plotAreaSpacing.X;
			rectangle.Y += this.plotAreaSpacing.Y;
			rectangle.Width -= this.plotAreaSpacing.X + this.plotAreaSpacing.Width;
			rectangle.Height -= this.plotAreaSpacing.Y + this.plotAreaSpacing.Height;
			if (!this.Area.Area3DStyle.Enable3D)
			{
				return rectangle;
			}
			RectangleF absoluteRectangle = this.Graph.GetAbsoluteRectangle(rectangle);
			Series dataSeries = this.GetDataSeries();
			if (dataSeries != null)
			{
				this._rotation3D = this.GetFunnelRotation(dataSeries);
			}
			float num = (float)Math.Abs((double)((absoluteRectangle.Width / 2f) * Math.Sin((((float)this._rotation3D) / 180f) * 3.1415926535897931)));
			float num2 = (float)Math.Abs((double)((absoluteRectangle.Width / 2f) * Math.Sin((((float)this._rotation3D) / 180f) * 3.1415926535897931)));
			if (this.isPyramid)
			{
				absoluteRectangle.Height -= num2;
			}
			else
			{
				absoluteRectangle.Y += num;
				absoluteRectangle.Height -= num + num2;
			}
			return this.Graph.GetRelativeRectangle(absoluteRectangle);
		}

		private void GetPlotAreaSpacing()
		{
			this.plotAreaSpacing = new RectangleF(1f, 1f, 1f, 1f);
			this.PlotAreaPosition = this.GetPlotAreaPosition();
			this.segmentList = this.GetFunnelSegmentPositions();
			if (!this.Area.InnerPlotPosition.Auto)
			{
				this.GetLabelsPosition();
			}
			else
			{
				for (int i = 0; !this.FitPointLabels() && (i < 5); i++)
				{
				}
			}
		}

		protected virtual void GetPointWidthAndHeight(Series series, int pointIndex, float location, out float height, out float startWidth, out float endWidth)
		{
			PointF empty = PointF.Empty;
			RectangleF absoluteRectangle = this.Graph.GetAbsoluteRectangle(this.PlotAreaPosition);
			float num = absoluteRectangle.Height - (this.funnelSegmentGap * (this.pointNumber - (this.ShouldDrawFirstPoint() ? 1 : 2)));
			if (num < 0f)
			{
				num = 0f;
			}
			if (this._funnelStyle == FunnelStyle.YIsWidth)
			{
				if (this._xValueTotal == 0.0)
				{
					height = num / ((float)(this.pointNumber - 1));
				}
				else
				{
					height = (float)(num * (this.GetXValue(series.Points[pointIndex]) / this._xValueTotal));
				}
				height = this.CheckMinHeight(height);
				startWidth = (float)(absoluteRectangle.Width * (this.GetYValue(series.Points[pointIndex - 1], pointIndex - 1) / this._yValueMax));
				endWidth = (float)(absoluteRectangle.Width * (this.GetYValue(series.Points[pointIndex], pointIndex) / this._yValueMax));
				empty = new PointF(absoluteRectangle.X + (absoluteRectangle.Width / 2f), location + height);
			}
			else
			{
				if (this._funnelStyle != FunnelStyle.YIsHeight)
				{
					throw new InvalidOperationException(SR.ExceptionFunnelStyleUnknown(this._funnelStyle.ToString()));
				}
				height = (float)(num * (this.GetYValue(series.Points[pointIndex], pointIndex) / this.yValueTotal));
				height = this.CheckMinHeight(height);
				PointF tf2 = ChartGraphics.GetLinesIntersection(absoluteRectangle.X, location, absoluteRectangle.Right, location, absoluteRectangle.X, absoluteRectangle.Y, (absoluteRectangle.X + (absoluteRectangle.Width / 2f)) - (this._funnelNeckSize.Width / 2f), absoluteRectangle.Bottom - this._funnelNeckSize.Height);
				PointF tf3 = ChartGraphics.GetLinesIntersection(absoluteRectangle.X, location + height, absoluteRectangle.Right, location + height, absoluteRectangle.X, absoluteRectangle.Y, (absoluteRectangle.X + (absoluteRectangle.Width / 2f)) - (this._funnelNeckSize.Width / 2f), absoluteRectangle.Bottom - this._funnelNeckSize.Height);
				startWidth = ((absoluteRectangle.X + (absoluteRectangle.Width / 2f)) - tf2.X) * 2f;
				endWidth = ((absoluteRectangle.X + (absoluteRectangle.Width / 2f)) - tf3.X) * 2f;
				empty = new PointF(absoluteRectangle.X + (absoluteRectangle.Width / 2f), location + (height / 2f));
			}
			series.Points[pointIndex].positionRel = this.Graph.GetRelativePoint(empty);
		}

		private PyramidValueType GetPyramidValueType(DataPointCustomProperties properties)
		{
			PyramidValueType linear = PyramidValueType.Linear;
			if (this.isPyramid)
			{
				string str = properties["PyramidValueType"];
				if ((str == null) || (str.Length <= 0))
				{
					return linear;
				}
				try
				{
					linear = (PyramidValueType)Enum.Parse(typeof(PyramidValueType), str, true);
				}
				catch
				{
					throw new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid(str, "PyramidValueType"));
				}
			}
			return linear;
		}

		public virtual double GetXValue(DataPoint point)
		{
			if (this.Area.AxisX.IsLogarithmic)
			{
				return Math.Abs(Math.Log(point.XValue, this.Area.AxisX.LogarithmBase));
			}
			return Math.Abs(point.XValue);
		}

		public virtual double GetYValue(DataPoint point, int pointIndex)
		{
			double a = 0.0;
			if (!point.IsEmpty)
			{
				a = point.YValues[0];
				if ((this._valuePercentages != null) && (this._valuePercentages.Length > pointIndex))
				{
					a = (a / 100.0) * this._valuePercentages[pointIndex];
				}
				if (this.Area.AxisY.IsLogarithmic)
				{
					return Math.Abs(Math.Log(a, this.Area.AxisY.LogarithmBase));
				}
				a = Math.Abs(a);
				if (a < this._funnelMinPointHeight)
				{
					a = this._funnelMinPointHeight;
				}
			}
			return a;
		}

		public virtual double GetYValue(CommonElements common, ChartArea area, Series series, DataPoint point, int pointIndex, int yValueIndex)
		{
			return point.YValues[yValueIndex];
		}

		private bool IsLabelsOverlap(FunnelPointLabelInfo testLabelInfo)
		{
			RectangleF position = testLabelInfo.Position;
			position.Inflate(1f, 1f);
			if (!testLabelInfo.Point.LabelBackColor.IsEmpty || (((testLabelInfo.Point.LabelBorderWidth > 0) && !testLabelInfo.Point.LabelBorderColor.IsEmpty) && (testLabelInfo.Point.LabelBorderDashStyle != ChartDashStyle.NotSet)))
			{
				position.Inflate(4f, 4f);
			}
			foreach (FunnelPointLabelInfo info in this.labelInfoList)
			{
				if (info.PointIndex == testLabelInfo.PointIndex)
				{
					break;
				}
				if (!info.Position.IsEmpty && info.Position.IntersectsWith(position))
				{
					return true;
				}
			}
			return false;
		}

		public virtual void Paint(ChartGraphics graph, CommonElements common, ChartArea area, Series seriesToDraw)
		{
			this._chartTypeSeries = null;
			this._funnelMinPointHeight = 0f;
			this.Graph = graph;
			this.Common = common;
			this.Area = area;
			this.GetDataPointValuesStatistic();
			if ((this.yValueTotal != 0.0) && (this.pointNumber != 0))
			{
				this._funnelStyle = this.GetFunnelStyle(this.GetDataSeries());
				if ((this._funnelStyle != FunnelStyle.YIsWidth) || (this.pointNumber != 1))
				{
					this.GetFunnelMinPointHeight(this.GetDataSeries());
					this.labelInfoList = this.CreateLabelsInfoList();
					this.GetPlotAreaSpacing();
					this.ProcessChartType();
					this.DrawLabels();
				}
			}
		}

		private void ProcessChartType()
		{
			if (this.Area.Area3DStyle.Enable3D && (((this._rotation3D > 0) && !this.isPyramid) || ((this._rotation3D < 0) && this.isPyramid)))
			{
				this.segmentList.Reverse();
			}
			bool flag = true;
			bool drawSegmentShadow = !this.Area.Area3DStyle.Enable3D;
			Series dataSeries = this.GetDataSeries();
			if ((drawSegmentShadow && flag) && ((dataSeries != null) && (dataSeries.ShadowOffset != 0)))
			{
				foreach (FunnelSegmentInfo info in this.segmentList)
				{
					this.DrawFunnelCircularSegment(info.Point, info.PointIndex, info.StartWidth, info.EndWidth, info.Location, info.Height, info.NothingOnTop, info.NothingOnBottom, false, true);
				}
				drawSegmentShadow = false;
			}
			foreach (FunnelSegmentInfo info2 in this.segmentList)
			{
				this.DrawFunnelCircularSegment(info2.Point, info2.PointIndex, info2.StartWidth, info2.EndWidth, info2.Location, info2.Height, info2.NothingOnTop, info2.NothingOnBottom, true, drawSegmentShadow);
			}
		}

		protected virtual bool ShouldDrawFirstPoint()
		{
			if (this._funnelStyle != FunnelStyle.YIsHeight)
			{
				return this.isPyramid;
			}
			return true;
		}

		public virtual bool ApplyPaletteColorsToPoints
		{
			get
			{
				return true;
			}
		}

		internal ChartArea Area { set; get; }

		public bool CircularChartArea
		{
			get
			{
				return false;
			}
		}

		internal CommonElements Common { set; get; }

		public virtual bool DataPointsInLegend
		{
			get
			{
				return true;
			}
		}

		public virtual bool ExtraYValuesConnectedToYAxis
		{
			get
			{
				return false;
			}
		}

		internal ChartGraphics Graph { set; get; }

		public virtual bool HundredPercent
		{
			get
			{
				return false;
			}
		}

		public virtual bool HundredPercentSupportNegative
		{
			get
			{
				return false;
			}
		}

		public virtual string Name
		{
			get
			{
				return "Funnel";
			}
		}

		internal RectangleF PlotAreaPosition
		{
			get
			{
				return this._plotAreaPosition;
			}
			set
			{
				this._plotAreaPosition = value;
			}
		}

		public virtual bool RequireAxes
		{
			get
			{
				return false;
			}
		}

		public virtual bool SecondYScale
		{
			get
			{
				return false;
			}
		}

		public virtual bool SideBySideSeries
		{
			get
			{
				return false;
			}
		}

		public virtual bool Stacked
		{
			get
			{
				return false;
			}
		}

		public bool StackSign
		{
			get
			{
				return false;
			}
		}

		public virtual bool SupportLogarithmicAxes
		{
			get
			{
				return true;
			}
		}

		public virtual bool SupportStackedGroups
		{
			get
			{
				return false;
			}
		}

		public virtual bool SwitchValueAxes
		{
			get
			{
				return false;
			}
		}

		public virtual int YValuesPerPoint
		{
			get
			{
				return 1;
			}
		}

		public virtual bool ZeroCrossing
		{
			get
			{
				return false;
			}
		}
	}
}

